home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / pico / basic.c < prev    next >
C/C++ Source or Header  |  1996-04-25  |  21KB  |  873 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: basic.c,v 4.26 1996/04/25 21:38:32 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    Cursor manipulation functions
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1996 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*
  31.  * The routines in this file move the cursor around on the screen. They
  32.  * compute a new value for the cursor, then adjust ".". The display code
  33.  * always updates the cursor location, so only moves between lines, or
  34.  * functions that adjust the top line in the window and invalidate the
  35.  * framing, are hard.
  36.  */
  37. #include        <stdio.h>
  38. #include        <ctype.h>
  39. #include    "osdep.h"
  40. #include        "pico.h"
  41. #include    "estruct.h"
  42. #include        "edef.h"
  43. #include        "efunc.h"
  44.  
  45.  
  46. #ifdef    ANSI
  47.     int getgoal(struct LINE *);
  48. #else
  49.     int getgoal();
  50. #endif
  51.  
  52.  
  53. /*
  54.  * Move the cursor to the
  55.  * beginning of the current line.
  56.  * Trivial.
  57.  */
  58. gotobol(f, n)
  59. int f, n;
  60. {
  61.     curwp->w_doto  = 0;
  62.     return (TRUE);
  63. }
  64.  
  65. /*
  66.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  67.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  68.  * location. Error if you try and move out of the buffer. Set the flag if the
  69.  * line pointer for dot changes.
  70.  */
  71. backchar(f, n)
  72. int             f;
  73. register int    n;
  74. {
  75.     register LINE   *lp;
  76.  
  77.     if (n < 0)
  78.       return (forwchar(f, -n));
  79.  
  80.     while (n--) {
  81.     if (curwp->w_doto == 0) {
  82.         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep){
  83.         if(Pmaster && Pmaster->headents)
  84.             /*
  85.              * go up into editing the mail header if on 
  86.              * the top line and the user hits the left arrow!!!
  87.              *
  88.              * if the editor returns anything except -1, the 
  89.              * user requested something special, so let 
  90.              * pico know...
  91.              */
  92.           return(HeaderEditor(2, 1));
  93.         else
  94.           return (FALSE);
  95.         }
  96.  
  97.         curwp->w_dotp  = lp;
  98.         curwp->w_doto  = llength(lp);
  99.         curwp->w_flag |= WFMOVE;
  100.     } else
  101.       curwp->w_doto--;
  102.     }
  103.  
  104.     return (TRUE);
  105. }
  106.  
  107.  
  108. /*
  109.  * Move the cursor to the end of the current line. Trivial. No errors.
  110.  */
  111. gotoeol(f, n)
  112. int f, n;
  113. {
  114.     curwp->w_doto  = llength(curwp->w_dotp);
  115.     return (TRUE);
  116. }
  117.  
  118.  
  119. /*
  120.  * Move the cursor forwwards by "n" characters. If "n" is less than zero call
  121.  * "backchar" to actually do the move. Otherwise compute the new cursor
  122.  * location, and move ".". Error if you try and move off the end of the
  123.  * buffer. Set the flag if the line pointer for dot changes.
  124.  */
  125. forwchar(f, n)
  126. int             f;
  127. register int    n;
  128. {
  129.     if (n < 0)
  130.       return (backchar(f, -n));
  131.  
  132.     while (n--) {
  133.     if (curwp->w_doto == llength(curwp->w_dotp)) {
  134.         if (curwp->w_dotp == curbp->b_linep)
  135.           return (FALSE);
  136.  
  137.         curwp->w_dotp  = lforw(curwp->w_dotp);
  138.         curwp->w_doto  = 0;
  139.         curwp->w_flag |= WFMOVE;
  140.     }
  141.     else
  142.       curwp->w_doto++;
  143.     }
  144.     
  145.     return (TRUE);
  146. }
  147.  
  148.  
  149. /*
  150.  * move to a particular line.
  151.  * argument (n) must be a positive integer for
  152.  * this to actually do anything
  153.  */
  154. gotoline(f, n)
  155. int f, n;
  156. {
  157.     if (n < 1)        /* if a bogus argument...then leave */
  158.       return(FALSE);
  159.  
  160.     /* first, we go to the start of the buffer */
  161.     curwp->w_dotp  = lforw(curbp->b_linep);
  162.     curwp->w_doto  = 0;
  163.     return(forwline(f, n-1));
  164. }
  165.  
  166.  
  167. /*
  168.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  169.  * considered to be hard motion; it really isn't if the original value of dot
  170.  * is the same as the new value of dot. Normally bound to "M-<".
  171.  */
  172. gotobob(f, n)
  173. int f, n;
  174. {
  175.     curwp->w_dotp  = lforw(curbp->b_linep);
  176.     curwp->w_doto  = 0;
  177.     curwp->w_flag |= WFHARD;
  178.     return (TRUE);
  179. }
  180.  
  181.  
  182. /*
  183.  * Move to the end of the buffer. Dot is always put at the end of the file
  184.  * (ZJ). The standard screen code does most of the hard parts of update.
  185.  * Bound to "M->".
  186.  */
  187. gotoeob(f, n)
  188. int f, n;
  189. {
  190.     curwp->w_dotp  = curbp->b_linep;
  191.     curwp->w_doto  = 0;
  192.     curwp->w_flag |= WFHARD;
  193.     return (TRUE);
  194. }
  195.  
  196.  
  197. /*
  198.  * Move forward by full lines. If the number of lines to move is less than
  199.  * zero, call the backward line function to actually do it. The last command
  200.  * controls how the goal column is set. Bound to "C-N". No errors are
  201.  * possible.
  202.  */
  203. forwline(f, n)
  204. int f, n;
  205. {
  206.     register LINE   *dlp;
  207.  
  208.     if (n < 0)
  209.       return (backline(f, -n));
  210.  
  211.     if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
  212.       curgoal = getccol(FALSE);       /* not C-P or C-N       */
  213.  
  214.     thisflag |= CFCPCN;
  215.     dlp = curwp->w_dotp;
  216.     while (n-- && dlp!=curbp->b_linep)
  217.       dlp = lforw(dlp);
  218.  
  219.     curwp->w_dotp  = dlp;
  220.     curwp->w_doto  = getgoal(dlp);
  221.     curwp->w_flag |= WFMOVE;
  222.     return (TRUE);
  223. }
  224.  
  225.  
  226. /*
  227.  * This function is like "forwline", but goes backwards. The scheme is exactly
  228.  * the same. Check for arguments that are less than zero and call your
  229.  * alternate. Figure out the new line and call "movedot" to perform the
  230.  * motion. No errors are possible. Bound to "C-P".
  231.  */
  232. backline(f, n)
  233. int f, n;
  234. {
  235.     register LINE   *dlp;
  236.     register int    status = 0;
  237.  
  238.     if (n < 0)
  239.       return (forwline(f, -n));
  240.  
  241.     if(Pmaster && Pmaster->headents){
  242.     /*
  243.      * go up into editing the mail header if on the top line
  244.      * and the user hits the up arrow!!!
  245.      */
  246.     if (lback(curwp->w_dotp) == curbp->b_linep)
  247.       /*
  248.        * if the editor returns anything except -1 then the user
  249.        * has requested something special, so let pico know...
  250.        */
  251.       return(HeaderEditor(1, 1));
  252.     }
  253.  
  254.     if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
  255.       curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
  256.  
  257.     thisflag |= CFCPCN;
  258.     dlp = curwp->w_dotp;
  259.     while (n-- && lback(dlp)!=curbp->b_linep)
  260.       dlp = lback(dlp);
  261.  
  262.     curwp->w_dotp  = dlp;
  263.     curwp->w_doto  = getgoal(dlp);
  264.     curwp->w_flag |= WFMOVE;
  265.     return (TRUE);
  266. }
  267.  
  268.  
  269. /*
  270.  * go back to the begining of the current paragraph
  271.  * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  272.  * combination to delimit the begining of a paragraph    
  273.  */
  274. gotobop(f, n)
  275. int f, n;    /* default Flag & Numeric argument */
  276. {
  277.     register int txt;
  278.  
  279.     if (n < 0)    /* the other way...*/
  280.       return(gotoeop(f, -n));
  281.  
  282.     while (n-- > 0) {    /* for each one asked for */
  283.  
  284.     /* is there text on the current line? */
  285.     for(txt = llength(curwp->w_dotp);
  286.         txt > 0 && isspace((unsigned char)lgetc(curwp->w_dotp, txt-1).c);
  287.         txt--)
  288.       ;
  289.  
  290.     if(!txt)
  291.       /* scan backward until we do find text */
  292.       while(lback(curwp->w_dotp) != curbp->b_linep
  293.         && (!llength(curwp->w_dotp)
  294.             || curwp->w_doto == llength(curwp->w_dotp)
  295.             || isspace((unsigned char)lgetc(curwp->w_dotp,
  296.                             curwp->w_doto).c)))
  297.         backchar(FALSE, 1);
  298.  
  299.     /* scan line by line until we come to a line ending with
  300.      * a <NL><NL> or <NL><TAB> or <NL><SPACE>
  301.      */
  302.     while(lback(curwp->w_dotp) != curbp->b_linep
  303.           && llength(lback(curwp->w_dotp))
  304.           && lgetc(curwp->w_dotp, 0).c != TAB
  305.           && lgetc(curwp->w_dotp, 0).c != ' ')
  306.       curwp->w_dotp = lback(curwp->w_dotp);
  307.  
  308.     if(n){
  309.         /* keep looking */
  310.         if(lback(curwp->w_dotp) == curbp->b_linep)
  311.           break;
  312.         else
  313.           curwp->w_dotp = lback(curwp->w_dotp);
  314.  
  315.         curwp->w_doto = 0;
  316.     }
  317.     else{
  318.       /* leave cursor on first word in para */
  319.         curwp->w_doto = 0;
  320.         while(isspace((unsigned char)lgetc(curwp->w_dotp, curwp->w_doto).c))
  321.           if(++curwp->w_doto >= llength(curwp->w_dotp)){
  322.           curwp->w_doto = 0;
  323.           curwp->w_dotp = lforw(curwp->w_dotp);
  324.           if(curwp->w_dotp == curbp->b_linep)
  325.             break;
  326.           }
  327.     }
  328.     }
  329.  
  330.     curwp->w_flag |= WFMOVE;    /* force screen update */
  331.     return(TRUE);
  332. }
  333.  
  334.  
  335. /* 
  336.  * go forword to the end of the current paragraph
  337.  * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  338.  * combination to delimit the begining of a paragraph
  339.  */
  340. gotoeop(f, n)
  341. int f, n;    /* default Flag & Numeric argument */
  342.  
  343. {
  344.     register int txt;
  345.  
  346.     if (n < 0)    /* the other way...*/
  347.       return(gotobop(f, -n));
  348.  
  349.     while (n-- > 0) {    /* for each one asked for */
  350.  
  351.     /* is there text on the current line? */
  352.     for(txt = llength(curwp->w_dotp);
  353.         txt > 0 && isspace((unsigned char)lgetc(curwp->w_dotp, txt-1).c);
  354.         txt--)
  355.       ;
  356.  
  357.     if(!txt)
  358.       /* scan forword until we do find text */
  359.       while(curwp->w_dotp != curbp->b_linep
  360.         && (!llength(curwp->w_dotp)
  361.             || curwp->w_doto == llength(curwp->w_dotp)
  362.             || isspace((unsigned char)lgetc(curwp->w_dotp,
  363.                             curwp->w_doto).c)))
  364.         forwchar(FALSE, 1);
  365.  
  366.     /* scan line by line until we come to a line ending with
  367.      * a <NL><NL> or <NL><TAB> or <NL><SPACE>
  368.      */
  369.     while(curwp->w_dotp != curbp->b_linep
  370.           && llength(lforw(curwp->w_dotp))
  371.           && lgetc(lforw(curwp->w_dotp), 0).c != TAB
  372.           && lgetc(lforw(curwp->w_dotp), 0).c != ' ')
  373.       curwp->w_dotp = lforw(curwp->w_dotp);
  374.  
  375.     curwp->w_doto = llength(curwp->w_dotp);
  376.  
  377.     /* still looking? */
  378.     if(n){
  379.         if(curwp->w_dotp == curbp->b_linep)
  380.           break;
  381.         else
  382.           curwp->w_dotp = lforw(curwp->w_dotp);
  383.  
  384.         curwp->w_doto = 0;
  385.     }
  386.     }
  387.  
  388.     curwp->w_flag |= WFMOVE;    /* force screen update */
  389.     return(curwp->w_dotp != curbp->b_linep);
  390. }
  391.  
  392. /*
  393.  * This routine, given a pointer to a LINE, and the current cursor goal
  394.  * column, return the best choice for the offset. The offset is returned.
  395.  * Used by "C-N" and "C-P".
  396.  */
  397. getgoal(dlp)
  398. register LINE   *dlp;
  399. {
  400.     register int    c;
  401.     register int    col;
  402.     register int    newcol;
  403.     register int    dbo;
  404.  
  405.     col = 0;
  406.     dbo = 0;
  407.     while (dbo != llength(dlp)) {
  408.     c = lgetc(dlp, dbo).c;
  409.     newcol = col;
  410.     if (c == '\t')
  411.       newcol |= 0x07;
  412.     else if (c<0x20 || c==0x7F)
  413.       ++newcol;
  414.  
  415.     ++newcol;
  416.     if (newcol > curgoal)
  417.       break;
  418.  
  419.     col = newcol;
  420.     ++dbo;
  421.     }
  422.  
  423.     return (dbo);
  424. }
  425.  
  426.  
  427.  
  428. /*
  429.  * Scroll the display forward (up) n lines.
  430.  */
  431. scrollforw (n, movedot)
  432. register int    n;
  433. int        movedot;
  434. {
  435.     register LINE   *lp;
  436.     LINE        *lp2;
  437.     register int    nl;
  438.     int            i;
  439.  
  440.     nl = n;
  441.     lp = curwp->w_linep;
  442.     while (n-- && lp!=curbp->b_linep)
  443.       lp = lforw(lp);
  444.  
  445.     if (movedot) {            /* Move dot to top of page. */
  446.     curwp->w_dotp  = lp;
  447.     curwp->w_doto  = 0;
  448.     }
  449.  
  450.     curwp->w_flag |= WFHARD;
  451.     if(lp == curbp->b_linep)
  452.       return(TRUE);
  453.     else
  454.       curwp->w_linep = lp;
  455.  
  456.     /*
  457.      * if the header is open, close it ...
  458.      */
  459.     if(Pmaster && Pmaster->headents && ComposerTopLine != COMPOSER_TOP_LINE){
  460.     n -= ComposerTopLine - COMPOSER_TOP_LINE;
  461.     ToggleHeader(0);
  462.     }
  463.  
  464.     /*
  465.      * scroll down from the top the same number of lines we've moved 
  466.      * forward
  467.      */
  468.     if(optimize)
  469.       scrollup(curwp, -1, nl-n-1);
  470.  
  471.     if(!movedot){
  472.     /* Requested to not move the dot.  Look for the dot in the current
  473.      * window.  loop through all lines, stop when at end of window
  474.      * or endof buffer.  If the dot is found, it can stay where it
  475.      * is, otherwise we do need to move it.
  476.      */
  477.     movedot = TRUE;
  478.     for (    lp2 = lp, i = 0; 
  479.         lp2 != curbp->b_linep && i < curwp->w_ntrows;  
  480.         lp2 = lforw(lp2), ++i) {
  481.         if (curwp->w_dotp == lp2) {
  482.          movedot = FALSE;
  483.          break;
  484.         }
  485.         }
  486.     if (movedot) {
  487.         /* Dot not found in window.  Move to first line of window. */
  488.         curwp->w_dotp  = lp;
  489.         curwp->w_doto  = 0;
  490.         }
  491.     }
  492.  
  493.     return (TRUE);
  494. }
  495.  
  496.  
  497. /*
  498.  * Scroll forward by a specified number of lines, or by a full page if no
  499.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  500.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  501.  * this zaps the top line in the display window, we have to do a hard update.
  502.  */
  503. forwpage(f, n)
  504. int             f;
  505. register int    n;
  506. {
  507.  
  508.     if (f == FALSE) {
  509.     n = curwp->w_ntrows - 2;        /* Default scroll.      */
  510.     if (n <= 0)                     /* Forget the overlap   */
  511.       n = 1;                  /* if tiny window.      */
  512.     } else if (n < 0)
  513.       return (backpage(f, -n));
  514. #if     CVMVAS
  515.     else                                    /* Convert from pages   */
  516.       n *= curwp->w_ntrows;           /* to lines.            */
  517. #endif
  518.     return (scrollforw (n, TRUE));
  519. }
  520.  
  521.  
  522. /*
  523.  * Scroll back (down) number of lines.  
  524.  */
  525. scrollback (n, movedot)
  526. register int    n;
  527. int        movedot;
  528. {
  529.     register LINE   *lp, *tp;
  530.     register int    nl;
  531.     int             status = 0;
  532.     int            i;
  533.  
  534.     if(Pmaster && Pmaster->headents){
  535.     /*
  536.      * go up into editing the mail header if on the top line
  537.      * and the user hits the up arrow!!!
  538.      */
  539.     if (lback(curwp->w_dotp) == curbp->b_linep){
  540.         /*
  541.          * if the editor returns anything except -1 then the user
  542.          * has requested something special, so let pico know...
  543.          */
  544.         return(HeaderEditor(1, 1));
  545.     }
  546.     }
  547.  
  548.     /*
  549.      * Count back the number of lines requested.
  550.      */
  551.     nl = n;
  552.     lp = curwp->w_linep;
  553.     while (n-- && lback(lp)!=curbp->b_linep)
  554.       lp = lback(lp);
  555.  
  556.     curwp->w_linep = lp;
  557.     curwp->w_flag |= WFHARD;
  558.  
  559.     /*
  560.      * scroll down from the top the same number of lines we've moved 
  561.      * forward
  562.      *
  563.      * This isn't too cool, but it has to be this way so we can 
  564.      * gracefully scroll in the message header
  565.      */
  566.     if(Pmaster && Pmaster->headents){
  567.     if((lback(lp)==curbp->b_linep) && (ComposerTopLine==COMPOSER_TOP_LINE))
  568.       n -= entry_line(1000, TRUE); /* never more than 1000 headers */
  569.     if(nl-n-1 < curwp->w_ntrows)
  570.       if(optimize)
  571.         scrolldown(curwp, -1, nl-n-1);
  572.     }
  573.     else
  574.       if(optimize)
  575.     scrolldown(curwp, -1, nl-n-1);
  576.  
  577.     if(Pmaster && Pmaster->headents){
  578.     /*
  579.      * if we're at the top of the page, and the header is closed, 
  580.      * open it ...
  581.      */
  582.     if((lback(lp) == curbp->b_linep) 
  583.        && (ComposerTopLine == COMPOSER_TOP_LINE)){
  584.         ToggleHeader(1);
  585.         movecursor(ComposerTopLine, 0);
  586.     }
  587.     }
  588.     
  589.     /*
  590.      * Decide if we move the dot or not.  Calculation done AFTER deciding
  591.      * if we display the header because that will change the number of
  592.      * lines on the screen.
  593.      */
  594.     if (movedot) {
  595.     /* Dot gets put at top of window. */
  596.     curwp->w_dotp  = curwp->w_linep;
  597.     curwp->w_doto  = 0;
  598.     }
  599.     else {
  600.     /* Requested not to move dot, but we do need to keep in on
  601.      * the screen.  Verify that it is still in the range of lines
  602.      * visable in the window.  Loop from the first line to the
  603.      * last line, until we reach the end of the buffer or the end
  604.      * of the window.  If we find the dot, then we don't need
  605.      * to move it. */
  606.     movedot = TRUE;
  607.     for (    tp = curwp->w_linep, i = 0; 
  608.         tp != curbp->b_linep && i < curwp->w_ntrows;  
  609.         tp = lforw(tp), ++i) {
  610.         if (curwp->w_dotp == tp) {
  611.          movedot = FALSE;
  612.          break;
  613.         }
  614.         }
  615.     if (movedot) {
  616.         /* Dot not found in window.  Move to last line of window. */
  617.         curwp->w_dotp  = lback (tp);
  618.         curwp->w_doto  = 0;
  619.         }
  620.     }
  621.  
  622.     return (TRUE);
  623. }
  624.  
  625.  
  626.  
  627.  
  628. /*
  629.  * This command is like "forwpage", but it goes backwards. The "2", like
  630.  * above, is the overlap between the two windows. The value is from the ITS
  631.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  632.  * reason.
  633.  */
  634. backpage(f, n)
  635. int             f;
  636. register int    n;
  637. {
  638.  
  639.     if (f == FALSE) {
  640.     n = curwp->w_ntrows - 2;        /* Default scroll.      */
  641.     if (n <= 0)                     /* Don't blow up if the */
  642.       n = 1;                  /* window is tiny.      */
  643.     } else if (n < 0)
  644.       return (forwpage(f, -n));
  645. #if     CVMVAS
  646.     else                                    /* Convert from pages   */
  647.       n *= curwp->w_ntrows;           /* to lines.            */
  648. #endif
  649.     return (scrollback (n, TRUE));
  650. }
  651.  
  652.  
  653.  
  654. scrollupline (f, n)
  655. int f, n;
  656. {
  657.     return (scrollback (1, FALSE));
  658. }
  659.  
  660.  
  661. scrolldownline (f, n)
  662. int f, n;
  663. {
  664.     return (scrollforw (1, FALSE));
  665. }
  666.  
  667.  
  668.  
  669. /*
  670.  * Scroll to a position.
  671.  */
  672. scrollto (f, n)
  673. int f, n;
  674. {
  675. #ifdef _WINDOWS
  676.     long    scrollLine;
  677.     LINE    *lp;
  678.     int        i;
  679.     
  680.     scrollLine = mswin_getscrollto ();
  681.     
  682.     /*
  683.      * Starting at the first data line in the buffer, step forward
  684.      * 'scrollLine' lines to find the new top line.  It is a circular
  685.      * list of buffers, so watch for the first line to reappear.  if
  686.      * it does, we have some sort of internal error, abort scroll
  687.      * operation.  Also watch for NULL, just in case.
  688.      */
  689.     lp = lforw (curbp->b_linep);
  690.     for (i = 0; i < scrollLine && lp != curbp->b_linep && lp != NULL; ++i)
  691.     lp = lforw(lp);
  692.  
  693.     if (lp == curbp->b_linep || lp == NULL)
  694.     return (FALSE);                    /* Whoops! */
  695.     
  696.  
  697.     /* Set the new top line for the window and flag a redraw. */
  698.     curwp->w_linep = lp;
  699.     curwp->w_dotp  = lp;
  700.     curwp->w_doto  = 0;
  701.     curwp->w_flag |= WFHARD;
  702.     
  703.     if(Pmaster && Pmaster->headents){
  704.     /*
  705.      * If we are at the top of the page and header not open, open it.
  706.      * If we are not at the top of the page and the header is open,
  707.      * close it.
  708.      */
  709.     if((lback(lp) == curbp->b_linep) 
  710.        && (ComposerTopLine == COMPOSER_TOP_LINE)){
  711.         ToggleHeader(1);
  712.         movecursor(ComposerTopLine, 0);
  713.     }
  714.     else if((lback(lp) != curbp->b_linep) 
  715.        && (ComposerTopLine != COMPOSER_TOP_LINE)){
  716.        ToggleHeader (0);
  717.         }
  718.     }
  719.  
  720.     return (TRUE);
  721. #endif
  722. }
  723.  
  724.  
  725.  
  726. /*
  727.  * Set the mark in the current window to the value of "." in the window. No
  728.  * errors are possible. Bound to "M-.".  If told to set an already set mark
  729.  * unset it.
  730.  */
  731. setmark(f, n)
  732. int f, n;
  733. {
  734.     if(!curwp->w_markp){
  735.         curwp->w_markp = curwp->w_dotp;
  736.         curwp->w_marko = curwp->w_doto;
  737.     emlwrite("Mark Set", NULL);
  738.     }
  739.     else{
  740.     /* clear inverse chars between here and dot */
  741.     markregion(0);
  742.     curwp->w_markp = NULL;
  743.     emlwrite("Mark UNset", NULL);
  744.     }
  745.  
  746. #ifdef    _WINDOWS
  747.     mswin_allowcopycut(curwp->w_markp ? kremove : NULL);
  748. #endif
  749.     return (TRUE);
  750. }
  751.  
  752.  
  753. /*
  754.  * Swap the values of "." and "mark" in the current window. This is pretty
  755.  * easy, bacause all of the hard work gets done by the standard routine
  756.  * that moves the mark about. The only possible error is "no mark". Bound to
  757.  * "C-X C-X".
  758.  */
  759. swapmark(f, n)
  760. int f, n;
  761. {
  762.     register LINE   *odotp;
  763.     register int    odoto;
  764.  
  765.     if (curwp->w_markp == NULL) {
  766.     if(Pmaster == NULL)
  767.       emlwrite("No mark in this window", NULL);
  768.     return (FALSE);
  769.     }
  770.  
  771.     odotp = curwp->w_dotp;
  772.     odoto = curwp->w_doto;
  773.     curwp->w_dotp  = curwp->w_markp;
  774.     curwp->w_doto  = curwp->w_marko;
  775.     curwp->w_markp = odotp;
  776.     curwp->w_marko = odoto;
  777.     curwp->w_flag |= WFMOVE;
  778.     return (TRUE);
  779. }
  780.  
  781.  
  782. /*
  783.  * Set the mark in the current window to the value of "." in the window. No
  784.  * errors are possible. Bound to "M-.".  If told to set an already set mark
  785.  * unset it.
  786.  */
  787. setimark(f, n)
  788. int f, n;
  789. {
  790.     curwp->w_imarkp = curwp->w_dotp;
  791.     curwp->w_imarko = curwp->w_doto;
  792.     return(TRUE);
  793. }
  794.  
  795.  
  796. /*
  797.  * Swap the values of "." and "mark" in the current window. This is pretty
  798.  * easy, bacause all of the hard work gets done by the standard routine
  799.  * that moves the mark about. The only possible error is "no mark". Bound to
  800.  * "C-X C-X".
  801.  */
  802. swapimark(f, n)
  803. int f, n;
  804. {
  805.     register LINE   *odotp;
  806.     register int    odoto;
  807.  
  808.     if (curwp->w_imarkp == NULL) {
  809.     if(Pmaster == NULL)
  810.       emlwrite("Programmer botch! No mark in this window", NULL);
  811.     return (FALSE);
  812.     }
  813.  
  814.     odotp = curwp->w_dotp;
  815.     odoto = curwp->w_doto;
  816.     curwp->w_dotp  = curwp->w_imarkp;
  817.     curwp->w_doto  = curwp->w_imarko;
  818.     curwp->w_imarkp = odotp;
  819.     curwp->w_imarko = odoto;
  820.     curwp->w_flag |= WFMOVE;
  821.     return (TRUE);
  822. }
  823.  
  824.  
  825.  
  826. #ifdef MOUSE
  827.  
  828. /*
  829.  * Handle a mouse down.
  830.  */
  831. mousepress (f, n)
  832. int f, n;
  833. {
  834.     MOUSEPRESS    mp;
  835.     LINE    *lp;
  836.     int    i;
  837.  
  838.  
  839.     mouse_get_last (NULL, &mp);
  840.  
  841.  
  842.     lp = curwp->w_linep;
  843.     i = mp.row - ((Pmaster && Pmaster->headents) ? ComposerTopLine : 2);
  844.     if (i < 0) {
  845.     if (Pmaster) {
  846.         /* Clear existing region. */
  847.         if (curwp->w_markp)
  848.         setmark(0,1);    
  849.  
  850.         /* Move to top of document before editing header. */
  851.         curwp->w_dotp = curwp->w_linep;
  852.         curwp->w_doto = 0;
  853.         curwp->w_flag |= WFMOVE;
  854.         update ();                /* And update. */
  855.  
  856.         return (HeaderEditor (1, 1));
  857.         }
  858.     }
  859.     else {
  860.     while(i-- && lp != curbp->b_linep)
  861.       lp = lforw(lp);
  862.  
  863.     curgoal = mp.col;
  864.     curwp->w_dotp = lp;
  865.     curwp->w_doto = getgoal(lp);
  866.     curwp->w_flag |= WFMOVE;
  867.  
  868.     if(mp.doubleclick)
  869.         setmark(0, 1);
  870.     }
  871. }
  872. #endif
  873.